package com.atguigu.tingshu.album.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
	@Autowired
	private TrackStatMapper trackStatMapper;
	@Autowired
	private AlbumInfoMapper albumInfoMapper;
	@Autowired
	private VodService vodService;
	@Autowired
	private VodConstantProperties vodConstantProperties;




	/**
	 * 保存声音
	 * @param userId 用户id
	 * @param trackInfo 封装的声音信息表
	 */
	@Override
	public void saveTrackInfo(Long userId, TrackInfo trackInfo) {
		//1. 根据专辑id查询专辑信息-更新专辑信息: 复用专辑封面图片
		Long albumId = trackInfo.getAlbumId();
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		//2.新增声音
		//2.1 设置声音额外基本信息(左图): 用户id,声音排序序号,状态,来源❤
		trackInfo.setUserId(userId);
		trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
		trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
		if (trackInfo.getCoverUrl() == null) {
			//如果用户没有上传封面,就默认使用专辑封面
			trackInfo.setCoverUrl(albumInfo.getCoverUrl());
		}
		//2.2 远程调用腾讯调拨平台获取音频详细信息
		TrackMediaInfoVo mediaInfoVo = vodService.getMediaInfo(trackInfo.getMediaFileId());
		if (mediaInfoVo != null) {
			trackInfo.setMediaDuration(BigDecimal.valueOf(mediaInfoVo.getDuration()));
			trackInfo.setMediaSize(mediaInfoVo.getSize());
			trackInfo.setMediaType(mediaInfoVo.getType());
		}
		//2.3 新增声音
		trackInfoMapper.insert(trackInfo);
		Long trackId = trackInfo.getId();
		//3. 更新专辑信息(包括声音数量)
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
		albumInfoMapper.updateById(albumInfo);
		//4. 初始化声音统计信息
		this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_PLAY, 0);
		this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_COLLECT, 0);
		this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_PRAISE, 0);
		this.saveTrackStat(trackId, SystemConstant.TRACK_STAT_COMMENT, 0);
		//5.调用点播平台发起音频文件审核任务(异步审核)
		String reviewTaskId = vodService.reviewTask(trackInfo.getMediaFileId());
		trackInfo.setReviewTaskId(reviewTaskId);
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_REVIEWING);
		trackInfoMapper.updateById(trackInfo);

	}

	/**
	 * 保存声音统计信息
	 * @param trackId 声音id
	 * @param statType 统计类型
	 * @param statNum 统计数值
	 */
	@Override
	public void saveTrackStat(Long trackId, String statType, int statNum) {
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statType);
		trackStat.setStatNum(statNum);
		trackStatMapper.insert(trackStat);
	}

	/**
	 * 条件分页查询当前用户声音列表
	 * @param pageInfo       分页对象
	 * @param trackInfoQuery 查询条件（用户ID，关键字，审核状态）
	 * @return
	 */
	@Override
	public Page<TrackListVo> getUserTrackPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery) {
		return trackInfoMapper.getUserTrackPage(pageInfo,trackInfoQuery);
	}

	/**
	 * 更新声音信息
	 * @param trackInfo
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateTrackInfo(TrackInfo trackInfo) {
		//1.判断声音文件是否变更(如果变更,获取最新音频详情,删除原来音频文件)
		Long userId = trackInfo.getUserId();
		TrackInfo trackInfoDB = trackInfoMapper.selectById(userId);
		//2.执行声音记录修改
		String mediaFileIdOld = trackInfoDB.getMediaFileId();
		String mediaFileIdNew = trackInfo.getMediaFileId();
		if (!mediaFileIdOld.equals(mediaFileIdNew)) {
			//2.1再次获取变更后音频文件详情
			TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(mediaFileIdNew);
			if (mediaInfo != null) {
				trackInfo.setMediaSize(mediaInfo.getSize());
				trackInfo.setMediaType(mediaInfo.getType());
				trackInfo.setMediaDuration(BigDecimal.valueOf(mediaInfo.getDuration()));
				//2.2从点播平台删除旧的音频文件
				vodService.deleteMedia(mediaFileIdOld);
			}
		}
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
		trackInfoMapper.updateById(trackInfo);
		//3.todo 对内容(文本,音频)进行再次审核

	}

	/**
	 * 查询声音统计信息
	 * @param trackId
	 * @return
	 */
	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
		return trackInfoMapper.getTrackStatVo(trackId);
	}


	/**
	 * 基于用户选择购买声音动态返回分集购买列表
	 *
	 * @param userId  用户ID
	 * @param trackId 选择购买声音ID
	 * @return [{name:"本集",price:1,trackCount:1},{name:"后10集",price:10,trackCount:10}...{name:"全集/45集",price:45,trackCount:45}] 待结算声音数量45
	 */
	@Override
	public List<Map<String, Object>> getUserFenJiBuyList(Long userId, Long trackId) {
		//1.根据声音id查询声音信息 得到所属专辑id 声音序号
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		Long albumId = trackInfo.getAlbumId();
		Integer orderNum = trackInfo.getOrderNum();
		//todo 没写完

		//4.远程调用"用户服务"获取已购买声音id列表
		List<Long> userPaidTrackIdList = userFeignClient.getUserPaidTrackIdList(albumId).getData();
		//5.如果存在已购声音id,将已购声音id排除掉得到整整未购买声音列表
		if (CollectionUtil.isEmpty(userPaidTrackIdList)) {

		}
		return null;
	}

	/**
	 * 删除声音
	 * @param id
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeTrackInfo(Long id) {
		//1.根据id查询要被删除声音记录,得到专辑id跟声音序号
		TrackInfo deletTrackInfo = trackInfoMapper.selectById(id);
		Long albumId = deletTrackInfo.getAlbumId();
		Integer orderNum = deletTrackInfo.getOrderNum();
		//2.更新声音序号,确保连续
		LambdaUpdateWrapper<TrackInfo> wrapper = new LambdaUpdateWrapper<>();
		//2.1更新条件
		wrapper.eq(TrackInfo::getAlbumId,albumId);
		wrapper.gt(TrackInfo::getOrderNum,orderNum);
		//2.2修改字段值
		wrapper.setSql("order_num = order_num - 1");
		trackInfoMapper.update(null, wrapper);
		//3.删除声音表记录
		trackInfoMapper.deleteById(id);
		//4.删除声音统计
		LambdaQueryWrapper<TrackStat> trackStatLambdaQueryWrapper = new LambdaQueryWrapper<>();
		trackStatLambdaQueryWrapper.eq(TrackStat::getTrackId,id);
		trackStatMapper.delete(trackStatLambdaQueryWrapper);
		//5.更新专辑包含声音数量
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
		albumInfoMapper.updateById(albumInfo);
		//6.删除点播平台音频文件
		vodService.deleteMedia(deletTrackInfo.getMediaFileId());
	}


	@Autowired
	private UserFeignClient userFeignClient;

	/**
	 * 分页查询当前用户可见声音列表-动态判断声音付费标识
	 * @param pageInfo
	 * @param albumId
	 * @param userId
	 * @return
	 */
	@Override
	public Page<AlbumTrackListVo> getAlbumTrackPage(Page<AlbumTrackListVo> pageInfo, Long albumId, Long userId) {
		//1.分页查询当前用户可见声音列表,todo 暂不考虑声音付费标识,默认vo对象AlbumTrackListVo付费标识:false
		pageInfo = trackInfoMapper.getAlbumTrackPage(pageInfo, albumId);
		//2.根据专辑id次查询专辑信息,得到付费类型,试听集数
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		//2.1 付费类型 0101-免费  0102-vip免费  0103-付费
		String payType = albumInfo.getPayType();
		//2.2 获取当前专辑免费试听集数
		Integer tracksForFree = albumInfo.getTracksForFree();
		//3.判断用户未登录情况
		if (userId == null) {
			//3.1 专辑付费类型: vip免费或付费
			if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType) || SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)) {
				//3.2 除去试听,其他声音将付费标识全部设置true
				pageInfo.getRecords()
						.stream()
						.filter(vo -> vo.getOrderNum() > tracksForFree)
						.forEach(vo -> vo.setIsShowPaidMark(true));
			}
		} else {
			//4.判断用户已登录情况
			//4.1 远程调用用户服务获取用户信息: 是否vip用户
			UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(userId).getData();
			Assert.notNull(userInfoVo, "用户：{}不存在！", userId);
			Boolean isVIP = false;
			if (1 == userInfoVo.getIsVip().intValue() && userInfoVo.getVipExpireTime().after(new Date())) {
				//会员标识必须是1,且会员过期时间大于当前系统时间
				isVIP = true;
			}
			Boolean isNeedCheck = false;
			//4.2 判断专辑付费类型=vip免费 当前用户是普通用户,都需要进一步判断声音购买情况

			if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType) && !isVIP) {
				isNeedCheck = true;
			}
			//4.3 判断专辑付费类型=付费 所有用户都需要进一步判断声音购买情况
			if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)) {
				isNeedCheck = true;
			}
			//4.4 远程调用用户服务获取本业中所有声音购买情况
			if (isNeedCheck) {
				//4.4.1 获取本页中需要检查购买情况的声音(去掉免费试听)
				List<Long> needCheckBuyStateTrackIds = pageInfo.getRecords()
						.stream()
						.filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree)
						.map(AlbumTrackListVo::getTrackId)
						.collect(Collectors.toList());
				//4.4.2 根据用户id+专辑+本业中声音id列表,远程调用用户服务检查声音购买情况
				Map<Long, Integer> buyStateMap = userFeignClient.userIsPaidTrack(userId, albumId, needCheckBuyStateTrackIds).getData();
				//4.5 根据本页中购买情况：如果声音购买状态为未购买（0）将付费标识改为：true
				pageInfo.getRecords()
						.stream()
						.filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree)
						.forEach(albumTrackListVo -> {
							//如果声音ID未购买，将付费标识设置true
							if (buyStateMap.get(albumTrackListVo.getTrackId()).intValue() == 0) {
								albumTrackListVo.setIsShowPaidMark(true);
							}
						});
			}
		}
		return pageInfo;
	}

@Autowired
private AlbumStatMapper albumStatMapper;

	/**
	 * 更新声音统计信息
	 * 注意:如果声音被播放,被评论,所属专辑也需要更新统计数值
	 * @param mqVo
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateStat(TrackStatMqVo mqVo) {
		//1.更新声音统计数据
		LambdaUpdateWrapper<TrackStat> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.eq(TrackStat::getTrackId, mqVo.getTrackId());
		updateWrapper.eq(TrackStat::getStatType, mqVo.getStatType());
		updateWrapper.setSql("stat_num=stat_num+" + mqVo.getCount());
		trackStatMapper.update(null,updateWrapper);
		//2.如果统计类型是: 声音播放 所属专辑统计信息也一并修改
		if (SystemConstant.TRACK_STAT_PLAY.equals(mqVo.getStatType())) {
			LambdaUpdateWrapper<AlbumStat> statLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
			statLambdaUpdateWrapper.eq(AlbumStat::getAlbumId,mqVo.getAlbumId());
			statLambdaUpdateWrapper.eq(AlbumStat::getStatType,SystemConstant.ALBUM_STAT_PLAY);
			statLambdaUpdateWrapper.setSql("stat_num = stat_num+" + mqVo.getCount());
			albumStatMapper.update(null,statLambdaUpdateWrapper);
		}
		//3.如果统计类型是: 声音评论 所属专辑统计信息也一并修改
		if (SystemConstant.TRACK_STAT_COMMENT.equals(mqVo.getStatType())) {
			LambdaUpdateWrapper<AlbumStat> statLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
			statLambdaUpdateWrapper.eq(AlbumStat::getAlbumId,mqVo.getAlbumId());
			statLambdaUpdateWrapper.eq(AlbumStat::getStatType,SystemConstant.ALBUM_STAT_COMMENT);
			statLambdaUpdateWrapper.setSql("stat_num = stat_num+" + mqVo.getCount());
			albumStatMapper.update(null,statLambdaUpdateWrapper);
		}
	}

}
